package helper

import (
	"errors"
	"github.com/dgrijalva/jwt-go"
	"lab-service/config"
	"time"
)

const (
	InvalidJwtToken = "invalid jwt token"
	ExpiredJwtToken = "expired jwt token"
)

func SignJwt(uid int64, rem bool, role, rdk string) (string, int64, error) {
	secCfg := config.GetConfig().SecurityService.Security
	var exp int64
	if rem {
		exp = time.Now().Add(secCfg.RememberExpiry).Unix()
	} else {
		exp = time.Now().Add(secCfg.JwtExpire).Unix()
	}
	//rdk := RandString(secCfg.RandKeyLen)
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"uid":  uid,
		"rdk":  rdk,
		"role": role,
		"exp":  exp,
	})
	// Sign and get the complete encoded token as a string using the secret
	jwtToken, err := token.SignedString([]byte(secCfg.GlobalToken))
	return jwtToken, exp, err
}

func VerifyJwt(jwtKey string) (jwt.MapClaims, error) {
	secCfg := config.GetConfig().SecurityService.Security
	token, err := jwt.Parse(jwtKey, func(token *jwt.Token) (interface{}, error) {
		// Don't forget to validate the alg is what you expect:
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			str := "Unexpected signing method: " + token.Header["alg"].(string)
			return nil, errors.New(str)
		}
		return []byte(secCfg.GlobalToken), nil
	})
	if token != nil && token.Claims != nil {
		if claims, ok := token.Claims.(jwt.MapClaims); ok {
			if token.Valid {
				// Token valid, everything is ok
				return claims, nil
			} else if ve, ok := err.(*jwt.ValidationError); ok && ve.Errors&(jwt.ValidationErrorExpired) != 0 {
				// Token is either expired
				return claims, errors.New(ExpiredJwtToken)
			}
		}
	}
	// Token valid failed
	return nil, errors.New(InvalidJwtToken)
}
